/*
 * Created on 2005-9-13
 *
 */
package bma.common.langutil.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * 
 * @author guanzhong
 * @since 1.0 (imported from BMA.ESP Project)
 */
public class ListUtil {

	/**
	 * 把Iterator转换为List
	 * 
	 * @param it
	 *            Iterator
	 * @return List
	 */
	public static List toList(Iterator it) {
		ArrayList<Object> r = new ArrayList<Object>();
		while (it.hasNext()) {
			r.add(it.next());
		}
		return r;
	}

	public static <V> List<V> toList(Iterator it, Class<V> cls) {
		List<V> r = new LinkedList<V>();
		while (it.hasNext()) {
			r.add(ClassUtil.cast(cls, it.next()));
		}
		return r;
	}

	public static <OUT_TYPE, IN_TYPE> List<OUT_TYPE> toList(
			Iterator<IN_TYPE> it, Function<? super IN_TYPE, OUT_TYPE> co) {
		List<OUT_TYPE> r = new LinkedList<OUT_TYPE>();
		while (it.hasNext()) {
			r.add(co.apply(it.next()));
		}
		return r;
	}

	public static <V> List<V> toList(Iterable it, Class<V> cls) {
		List<V> r = new LinkedList<V>();
		for (Object o : it) {
			r.add(ClassUtil.cast(cls, o));
		}
		return r;
	}

	public static <OUT_TYPE, IN_TYPE> List<OUT_TYPE> toList(
			Iterable<IN_TYPE> it, Function<? super IN_TYPE, OUT_TYPE> co) {
		List<OUT_TYPE> r = new LinkedList<OUT_TYPE>();
		for (IN_TYPE o : it) {
			r.add(co.apply(o));
		}
		return r;
	}

	public static <V> List<V> filter(Iterable it, Class<V> cls) {
		List<V> r = new LinkedList<V>();
		for (Object o : it) {
			V v = ClassUtil.cast(cls, o);
			if (v != null)
				r.add(v);
		}
		return r;
	}

	public static <V, PARAM_TYPE> List<V> filter(Iterable<V> it,
			ObjectFilter<? super V, PARAM_TYPE> filter, PARAM_TYPE param) {
		if (it == null)
			return null;
		List<V> r = new LinkedList<V>();
		filter(it, filter, param, r);
		return r;
	}

	public static <V, PARAM_TYPE> void filter(Iterable<V> it,
			ObjectFilter<? super V, PARAM_TYPE> filter, PARAM_TYPE param,
			List<V> result) {
		if (it == null)
			return;
		for (V v : it) {
			if (filter == null || filter.accept(v, param))
				result.add(v);
		}
	}

	public static <V, PARAM_TYPE> V filterOne(Iterable<V> it,
			ObjectFilter<? super V, PARAM_TYPE> filter, PARAM_TYPE param) {
		if (it == null)
			return null;
		for (V v : it) {
			if (filter == null || filter.accept(v, param))
				return v;
		}
		return null;
	}

	public static <V, PARAM_TYPE, RESULT_TYPE> boolean walk(Iterable<V> it,
			ObjectWalker<? super V, PARAM_TYPE, RESULT_TYPE> walker,
			PARAM_TYPE param, RESULT_TYPE result) {
		if (it == null)
			return true;
		for (V v : it) {
			if (!walker.walk(v, param, result))
				return false;
		}
		return true;
	}
}
